<template>
  <div class="input-wrapper" :class="wrapperClass">
    <!-- 标签 -->
    <label v-if="label" :for="inputId" class="input-label">
      {{ label }}
      <span v-if="required" class="input-required">*</span>
    </label>

    <!-- 输入框容器 -->
    <div class="input-container" :class="containerClass">
      <!-- 前置图标 -->
      <div v-if="prefixIcon" class="input-prefix">
        <Icon :name="prefixIcon" :size="iconSize" />
      </div>

      <!-- 前置插槽 -->
      <div v-if="$slots.prefix" class="input-prefix">
        <slot name="prefix"></slot>
      </div>

      <!-- 输入框 -->
      <input
        :id="inputId"
        ref="inputRef"
        :class="inputClass"
        :type="inputType"
        :value="modelValue"
        :placeholder="placeholder"
        :disabled="disabled"
        :readonly="readonly"
        :maxlength="maxlength"
        :minlength="minlength"
        :max="max"
        :min="min"
        :step="step"
        :autocomplete="autocomplete"
        :autofocus="autofocus"
        v-bind="$attrs"
        @input="handleInput"
        @change="handleChange"
        @focus="handleFocus"
        @blur="handleBlur"
        @keydown="handleKeydown"
        @keyup="handleKeyup"
        @keypress="handleKeypress"
      />

      <!-- 密码显示切换 -->
      <div
        v-if="type === 'password' && showPasswordToggle"
        class="input-suffix input-password-toggle"
        @click="togglePasswordVisibility"
      >
        <Icon :name="showPassword ? 'eye-off' : 'eye'" :size="iconSize" />
      </div>

      <!-- 清空按钮 -->
      <div
        v-if="clearable && modelValue && !disabled && !readonly"
        class="input-suffix input-clear"
        @click="handleClear"
      >
        <Icon name="x" :size="iconSize" />
      </div>

      <!-- 后置图标 -->
      <div v-if="suffixIcon" class="input-suffix">
        <Icon :name="suffixIcon" :size="iconSize" />
      </div>

      <!-- 后置插槽 -->
      <div v-if="$slots.suffix" class="input-suffix">
        <slot name="suffix"></slot>
      </div>

      <!-- 加载状态 -->
      <div v-if="loading" class="input-suffix">
        <Icon name="refresh" :size="iconSize" spin />
      </div>
    </div>

    <!-- 字数统计 -->
    <div
      v-if="showCount && maxlength"
      class="input-count"
      :class="{ 'count-exceeded': currentLength > maxlength }"
    >
      {{ currentLength }} / {{ maxlength }}
    </div>

    <!-- 帮助文本 -->
    <div v-if="helpText" class="input-help">
      {{ helpText }}
    </div>

    <!-- 错误信息 -->
    <div v-if="errorMessage" class="input-error">
      <Icon name="alert-circle" size="14" />
      {{ errorMessage }}
    </div>

    <!-- 成功信息 -->
    <div v-if="successMessage" class="input-success">
      <Icon name="check-circle" size="14" />
      {{ successMessage }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick } from "vue";
import { generateId } from "@/utils";
import Icon from "./Icon.vue";

interface Props {
  // 基础属性
  modelValue?: string | number;
  type?: "text" | "password" | "email" | "number" | "tel" | "url" | "search";
  placeholder?: string;
  disabled?: boolean;
  readonly?: boolean;

  // 尺寸和样式
  size?: "mini" | "small" | "medium" | "large";
  variant?: "outlined" | "filled" | "underlined";

  // 验证
  required?: boolean;
  maxlength?: number;
  minlength?: number;
  max?: number | string;
  min?: number | string;
  step?: number | string;

  // 标签和提示
  label?: string;
  helpText?: string;
  errorMessage?: string;
  successMessage?: string;

  // 图标
  prefixIcon?: string;
  suffixIcon?: string;

  // 功能
  clearable?: boolean;
  showPasswordToggle?: boolean;
  showCount?: boolean;
  loading?: boolean;

  // HTML 属性
  autocomplete?: string;
  autofocus?: boolean;

  // 其他
  id?: string;
}

const props = withDefaults(defineProps<Props>(), {
  type: "text",
  size: "medium",
  variant: "outlined",
  showPasswordToggle: true,
});

const emit = defineEmits<{
  "update:modelValue": [value: string | number];
  input: [value: string | number, event: Event];
  change: [value: string | number, event: Event];
  focus: [event: FocusEvent];
  blur: [event: FocusEvent];
  clear: [];
  keydown: [event: KeyboardEvent];
  keyup: [event: KeyboardEvent];
  keypress: [event: KeyboardEvent];
}>();

// 响应式数据
const inputRef = ref<HTMLInputElement>();
const focused = ref(false);
const showPassword = ref(false);

// 计算属性
const inputId = computed(() => props.id || generateId("input"));

const inputType = computed(() => {
  if (props.type === "password") {
    return showPassword.value ? "text" : "password";
  }
  return props.type;
});

const currentLength = computed(() => {
  return String(props.modelValue || "").length;
});

const iconSize = computed(() => {
  const sizeMap = {
    mini: 12,
    small: 14,
    medium: 16,
    large: 18,
  };
  return sizeMap[props.size];
});

const wrapperClass = computed(() => {
  const classes = ["input-wrapper"];

  classes.push(`input-wrapper-${props.size}`);
  classes.push(`input-wrapper-${props.variant}`);

  if (props.disabled) classes.push("input-wrapper-disabled");
  if (props.readonly) classes.push("input-wrapper-readonly");
  if (focused.value) classes.push("input-wrapper-focused");
  if (props.errorMessage) classes.push("input-wrapper-error");
  if (props.successMessage) classes.push("input-wrapper-success");

  return classes.join(" ");
});

const containerClass = computed(() => {
  const classes = ["input-container"];

  classes.push(`input-container-${props.size}`);
  classes.push(`input-container-${props.variant}`);

  if (props.disabled) classes.push("input-container-disabled");
  if (props.readonly) classes.push("input-container-readonly");
  if (focused.value) classes.push("input-container-focused");
  if (props.errorMessage) classes.push("input-container-error");
  if (props.successMessage) classes.push("input-container-success");

  return classes.join(" ");
});

const inputClass = computed(() => {
  const classes = ["input"];

  classes.push(`input-${props.size}`);
  classes.push(`input-${props.variant}`);

  return classes.join(" ");
});

// 事件处理
const handleInput = (event: Event) => {
  const target = event.target as HTMLInputElement;
  let value: string | number = target.value;

  // 数字类型转换
  if (props.type === "number" && value !== "") {
    value = Number(value);
  }

  emit("update:modelValue", value);
  emit("input", value, event);
};

const handleChange = (event: Event) => {
  const target = event.target as HTMLInputElement;
  let value: string | number = target.value;

  if (props.type === "number" && value !== "") {
    value = Number(value);
  }

  emit("change", value, event);
};

const handleFocus = (event: FocusEvent) => {
  focused.value = true;
  emit("focus", event);
};

const handleBlur = (event: FocusEvent) => {
  focused.value = false;
  emit("blur", event);
};

const handleKeydown = (event: KeyboardEvent) => {
  emit("keydown", event);
};

const handleKeyup = (event: KeyboardEvent) => {
  emit("keyup", event);
};

const handleKeypress = (event: KeyboardEvent) => {
  emit("keypress", event);
};

const handleClear = () => {
  emit("update:modelValue", "");
  emit("clear");

  // 聚焦输入框
  nextTick(() => {
    inputRef.value?.focus();
  });
};

const togglePasswordVisibility = () => {
  showPassword.value = !showPassword.value;
};

// 公开方法
const focus = () => {
  inputRef.value?.focus();
};

const blur = () => {
  inputRef.value?.blur();
};

const select = () => {
  inputRef.value?.select();
};

defineExpose({
  focus,
  blur,
  select,
  inputRef,
});
</script>

<style scoped>
.input-wrapper {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.input-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.input-required {
  color: var(--error-color);
  margin-left: 2px;
}

.input-container {
  position: relative;
  display: flex;
  align-items: center;
  border-radius: 6px;
  transition: all 0.2s ease;
  background-color: var(--input-bg);
}

/* 尺寸 */
.input-container-mini {
  height: 24px;
}

.input-container-small {
  height: 32px;
}

.input-container-medium {
  height: 40px;
}

.input-container-large {
  height: 48px;
}

/* 变体样式 */
.input-container-outlined {
  border: 1px solid var(--border-color);
}

.input-container-outlined:hover:not(.input-container-disabled) {
  border-color: var(--border-color-hover);
}

.input-container-outlined.input-container-focused {
  border-color: var(--primary-color);
  box-shadow: 0 0 0 3px var(--primary-color-alpha);
}

.input-container-filled {
  border: 1px solid transparent;
  background-color: var(--bg-secondary);
}

.input-container-filled:hover:not(.input-container-disabled) {
  background-color: var(--hover-bg);
}

.input-container-filled.input-container-focused {
  background-color: var(--input-bg);
  border-color: var(--primary-color);
  box-shadow: 0 0 0 3px var(--primary-color-alpha);
}

.input-container-underlined {
  border: none;
  border-bottom: 2px solid var(--border-color);
  border-radius: 0;
  background-color: transparent;
}

.input-container-underlined:hover:not(.input-container-disabled) {
  border-bottom-color: var(--border-color-hover);
}

.input-container-underlined.input-container-focused {
  border-bottom-color: var(--primary-color);
}

/* 状态样式 */
.input-container-error {
  border-color: var(--error-color) !important;
}

.input-container-error.input-container-focused {
  box-shadow: 0 0 0 3px var(--error-color-alpha) !important;
}

.input-container-success {
  border-color: var(--success-color) !important;
}

.input-container-success.input-container-focused {
  box-shadow: 0 0 0 3px var(--success-color-alpha) !important;
}

.input-container-disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background-color: var(--bg-disabled) !important;
}

.input-container-readonly {
  background-color: var(--bg-secondary);
}

/* 输入框 */
.input {
  flex: 1;
  border: none;
  outline: none;
  background: transparent;
  color: var(--text-primary);
  font-size: 14px;
  line-height: 1.5;
  padding: 0 12px;
}

.input::placeholder {
  color: var(--text-placeholder);
}

.input:disabled {
  cursor: not-allowed;
}

.input:read-only {
  cursor: default;
}

/* 尺寸调整 */
.input-mini .input {
  padding: 0 8px;
  font-size: 12px;
}

.input-small .input {
  padding: 0 10px;
  font-size: 13px;
}

.input-large .input {
  padding: 0 14px;
  font-size: 15px;
}

/* 前缀和后缀 */
.input-prefix,
.input-suffix {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--text-tertiary);
  padding: 0 8px;
}

.input-prefix {
  border-right: 1px solid var(--border-color);
  margin-right: 8px;
}

.input-suffix {
  border-left: 1px solid var(--border-color);
  margin-left: 8px;
}

.input-password-toggle,
.input-clear {
  cursor: pointer;
  transition: color 0.2s ease;
  border: none;
  margin: 0;
  padding: 0 8px;
}

.input-password-toggle:hover,
.input-clear:hover {
  color: var(--text-primary);
}

/* 字数统计 */
.input-count {
  font-size: 12px;
  color: var(--text-tertiary);
  text-align: right;
  margin-top: 4px;
}

.count-exceeded {
  color: var(--error-color);
}

/* 帮助文本 */
.input-help {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 4px;
}

/* 错误信息 */
.input-error {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--error-color);
  margin-top: 4px;
}

/* 成功信息 */
.input-success {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--success-color);
  margin-top: 4px;
}

/* 响应式 */
@media (max-width: 768px) {
  .input-container-large {
    height: 44px;
  }

  .input-container-medium {
    height: 36px;
  }

  .input-large .input {
    font-size: 14px;
  }
}

/* 暗色主题适配 */
@media (prefers-color-scheme: dark) {
  .input-container-filled {
    background-color: var(--bg-tertiary);
  }

  .input-container-filled:hover:not(.input-container-disabled) {
    background-color: var(--bg-secondary);
  }
}

/* 动画效果 */
.input-container {
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.input-wrapper-focused .input-container {
  transform: translateY(-1px);
}

/* 自动填充样式 */
.input:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--input-bg) inset;
  -webkit-text-fill-color: var(--text-primary);
}

.input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--input-bg) inset;
  -webkit-text-fill-color: var(--text-primary);
}
</style>
